常常在工作中遇到某一些文字檔是由許多編碼不同的文字段組成,因為大型爬蟲爬下來的各種網頁有時候並沒有正確的把網頁原始編碼轉換成'utf8',導致大部份文字的編碼都是'utf8',但是有少部份的段落為其他編碼。
當我需要讀取這種文字檔做處理並更新寫入到另一個檔案的時候,要如何才能夠避免decode error,並且把非'utf8'編碼的字節原封不動寫入到另一個檔案?
用open的errors參數可以解決這種問題,但是把errors設置成'ignore'和'replace'都會改變非'utf8'編碼的文字段,且不可逆,所以無法把非'utf8'編碼的字節原封不動寫入到另一個檔案。
幸好還有另一個選項'surrogateescape'可以設置,他是一個可逆的錯誤機制處理,把'utf8'無法解析的字元映射成另一種代理字元,這種代理字元的編碼段和'utf8'用到的編碼段是獨立開來的,所以在我們逐行讀取時,若發現某一行文字含有這種代理字元的編碼段,就可知這行文字無法被'utf8'解析,然後我們就能略過他。
現在我們要把這行含有代理字元編碼段的文字轉換回來並寫入到另一個檔案裡,那這個新的檔案也必須把errors參數設為'surrogateescape',才能有效辨識代理字元編碼並將其轉換回來。
程式範例:
with open('test.txt','rt',errors='surrogateescape') as rf,\
open('new_test.txt','wt',errors='surrogateescape') as wf:
for line in rf:
if have_surrogate_char(line):
wf.write(line)
else:
new_line = process(line)
wf.write(new_line)